/* 
 * File:   Rede.h
 * Author: Luciano
 *
 * Created on 30 de Junho de 2011, 17:35
 */

#ifndef REDE_H
#define	REDE_H



#include "Layer.hpp"
using namespace ufpb::project::network;

class Rede : public Layer{
public:
    Rede();
    Rede(std::map<std::string, std::string>* conf);
//    Rede(const Rede& orig);
    const static int BROADCAST_OFFSET = 0;
    const static int BROADCAST_LENGTH = 1;
    const static int BROADCAST_RANGE = 2;
    
    const static int MEU_IP_LENGTH = 4;
    const static int MEU_IP_OFFSET = 5;
    const static int MEU_IP_RANGE = 16;

    const static int MAC_DESTINO_LENGTH = 4;
    const static int MAC_DESTINO_OFFSET = 1;
    const static int MAC_DESTINO_RANGE = 16;
    
    const static int CABECALHO_LENGTH = MAC_DESTINO_LENGTH + MEU_IP_LENGTH + BROADCAST_LENGTH;
    
    virtual ~Rede();
    void newMessageToSend(Bits* m);
    void newReceivedMessage(Bits* m);
    
    void leDoArquivo(std::string nomeDoArquivo);
    std::map<int, int>* getMapaDeIPs();
private:
    bool souOGateway;
    int meuIP;
    int meuMAC;
    int ipGateway;
    int macDestinoPadrao;
    std::map<int, int> mapaDeIPs;
    
    
    /**
     * Monta o pacote da camada de rede que e' enviado para camada de enlace
     * @param dadosAEnviar
     * @param macParaEnviar
     * @param isBroadcast
     * @return pacote
     */
    Bits* montaQuadro(Bits* dadosAEnviar, int macParaEnviar, bool isBroadcast);
    
    /**
     * Desmonta o pacote que chega da camada de enlace
     * @param dadosRecebidos
     * @return pacote
     */
    Bits* desmontaQuadro(Bits* dadosRecebidos);
    
    /**
     * Configura a camada de rede, lendo algumas propriedades salvas em arquivo
     */
    void configurarMapaDeIPs();
    
    /**
     * Retorna o MAC para o qual o pacote deve ser enviado
     * @return MAC
     */
    int getMacParaEnviar();
    
    /**
     * Retorna o MAC correspondente ao IP passado. Busca no mapa de IPs
     * @param IP
     * @return 
     */
    int getMac(int IP);
    
    /**
     * Dado o IP de destino, decide se ele pertence a nossa rede ou não
     * @param ipDestino
     * @return true se pertencer, false caso contrário
     */
    bool IPpertencenteARede(int ipDestino);
    
    /**
     * Dado o IP, retorna se ele e' de broadcast ou nao
     * @param dadosAEnviar
     * @return true se for de broadcast, false caso contrario
     */
    bool isBroadcast(Bits* dados);
    
    /**
     * Retorna o IP de destino gravado no quadro que chega da camada de transporte
     * @param dadosAEnviar
     * @return IP
     */
    int getIpDestinoEnviando(Bits* dadosAEnviar);
    
    /**
     * Retorna o IP de origem gravado no quadro que chega da camada de enlace
     * @param dadosAEnviar
     * @return IP de origem
     */
    int getIpOrigemRecebendo(Bits* dadosAEnviar);
    
    /**
     * Retorna o IP de destino gravado no quadro que chega da camada de enlace
     * @param dadosRecebidos
     * @return IP de destino
     */
    int getIpDestinoRecebendo(Bits* dadosRecebidos);
    
};

#endif	/* REDE_H */

